package com.yuuzy.dao;

import com.alibaba.druid.util.StringUtils;
import com.yuuzy.model.Buy_Wip;
import com.yuuzy.model.Client;
import com.yuuzy.model.Wip;
import com.yuuzy.utils.DBUtils;
import org.apache.commons.dbutils.DbUtils;
import org.apache.commons.dbutils.QueryRunner;

import java.sql.Connection;
import java.sql.Date;
import java.sql.SQLException;
import java.util.List;

public class Buy_WipDAO extends BasicDAO<Buy_Wip> {
    private QueryRunner qr = new QueryRunner();

    /**
     * 查询购买理财产品的数据
     *
     * @param buy_wip 待查询的购买理财产品类（传入产品id和客户id，不传入默认查询全部记录）
     * @return 查询到的购买理财产品类集
     */
    public List<Buy_Wip> queryBuy_Wip(Buy_Wip buy_wip) {
        StringBuilder sb = new StringBuilder("select * from buy_wip");
        if (buy_wip.getWip_id() != null && buy_wip.getClient_id() != null) {
            //根据客户id和理财产品id查询
            sb.append(" and wip_id = ").append(buy_wip.getWip_id());
            sb.append(" and client_id = ").append(buy_wip.getClient_id());
        }
        String sql = sb.toString().replaceFirst("and", "where");
        return queryMulti(sql, Buy_Wip.class);
    }

    /**
     * 增加购买理财产品记录
     *
     * @param buy_wip 待传入的购买理财产品实体
     * @return 受影响的行数
     */
    public int insertBuy_Wip(Buy_Wip buy_wip) {
        String sql = "INSERT INTO finance.buy_wip(wip_id,client_id,buy_wip_time,buy_wip_quantity,buy_wip_assetstatus,buy_wip_earnings) VALUES (?,?,?,?,?,?)";
        return update(sql, buy_wip.getWip_id(), buy_wip.getClient_id(), buy_wip.getBuy_wip_time(), buy_wip.getBuy_wip_quantity(), buy_wip.getBuy_wip_assetstatus(), buy_wip.getBuy_wip_earnings());
    }

    /**
     * 删除购买理财产品的数据
     *
     * @param buy_wip 待删除的购买理财产品类（必须包含客户id和理财产品id）
     * @return 受影响的行数
     */
    public int deleteBuy_Wip(Buy_Wip buy_wip) {
        StringBuilder sb = new StringBuilder("DELETE FROM buy_wip");
        if (buy_wip.getClient_id() != null && buy_wip.getWip_id() != null) {
            sb.append(" and client_id = ").append(buy_wip.getClient_id());
            sb.append(" and buy_wip_id = ").append(buy_wip.getWip_id());
        }
        String sql = sb.toString().replaceFirst("and", "where");
        return update(sql);
    }

    /**
     * 更新购买理财产品记录
     *
     * @param buy_wip 待更新的购买理财产品类
     * @return 受影响的行数
     */
    public int updateBuy_Wip(Buy_Wip buy_wip) {
        //客户id和理财产品id不能更改
        StringBuilder sb = new StringBuilder("UPDATE buy_wip SET ");
        if (buy_wip.getBuy_wip_time() != null) {
            //如果购买日期字段存在
            sb.append(",buy_wip_time = '").append(buy_wip.getBuy_wip_time()).append("'");
        }
        if (buy_wip.getBuy_wip_quantity() != null) {
            //如果数量字段存在
            sb.append(",buy_wip_quantity = ").append(buy_wip.getBuy_wip_quantity());
        }
        if (!StringUtils.isEmpty(buy_wip.getBuy_wip_assetstatus())) {
            //如果状态字段存在
            sb.append(",buy_wip_assetstatus = '").append(buy_wip.getBuy_wip_assetstatus()).append("'");
        }
        if (buy_wip.getBuy_wip_earnings() != null) {
            //如果收益字段存在
            sb.append(",buy_wip_earnings = ").append(buy_wip.getBuy_wip_earnings());
        }
        String sql = sb.append(" WHERE client_id = ? and wip_id = ?").toString().replaceFirst(",", "");
        return update(sql, buy_wip.getClient_id(), buy_wip.getWip_id());
    }

    /*
    购买理财产品
    设计思路：
    传入一个客户类，必须包含用户名和密码
    传入一个理财产品类，必须包含购买的理财产品id
    传入一个int类型参数，指明购买的理财产品份数
    返回一个Buy_Wip类

    （1）调用ClientDAO中的查询方法，获得完整的客户对象
    （2）调用WipDAO中的查询方法，获得完整的理财产品对象
    （3）先判断remain = （账户余额-理财产品金额*购买份数）是否大于0，若小于0，结束进程,返回null
    （4）若大于0，先查找表中是否有此类购买理财产品对象的记录，若有没有，则：
    （4.1）创建一个Buy_Wip类，将基本信息存入，并执行以下事务：
        向buy_wip表中增加一条记录
        修改客户账户内余额
        结束事务，返回创建好的Buy_Wip类
     若已存在此类理财产品对象的记录，则：
     （4.2）执行以下事务：
        更新buy_wip对象中的quantity字段
        修改客户账户内余额
        结束事务，返回修改好的Buy_Wip类
     */

    /**
     * @param client   客户类
     * @param wip      客户拟购买的理财产品类
     * @param quantity 购买数量
     * @return 购买理财产品类
     */
    public Buy_Wip buyWip(Client client, Wip wip, int quantity) {
        ClientDAO clientDAO = new ClientDAO();
        //（1）调用ClientDAO中的查询方法，获得完整的客户对象
        List<Client> clientList = clientDAO.queryClient(client);
        client = clientList.get(0);//去除第一个客户，也只可能有一个客户
        //（2）调用WipDAO中的查询方法，获得完整的理财产品对象
        List<Wip> wipList = new WipDAO().queryWip(wip);
        wip = wipList.get(0);//取出第一项理财产品，也只可能有一项理财产品
        //（3）先判断remain = （账户余额-理财产品金额*购买份数）是否大于0
        double remain = client.getClient_balance() - wip.getWip_amount() * quantity;
        if (remain < 0) {
            //余额小于0，购买失败
            System.out.println("余额不足");
            return null;
        }
        //（4）若大于0，先查找表中是否有此类理财产品对象的记录
        client.setClient_balance(remain);//设置购买后的余额
        Connection conn = null;
        Buy_Wip buyWip = null;
        List<Buy_Wip> buy_wips = queryBuy_Wip(new Buy_Wip(wip.getWip_id(), client.getClient_id()));
        //执行（4.1）的事务
        //（4.1）创建一个Buy_Wip类，将基本信息存入，并执行以下事务：
        //        向buy_wip表中增加一条记录
        //        修改客户账户内余额
        //        结束事务，返回创建好的Buy_Wip类
        if (buy_wips.isEmpty()) {
            //客户没有购买过该产品
            try {
                conn = DBUtils.getConnection();
                //开始事务
                conn.setAutoCommit(false);
                buyWip = new Buy_Wip(wip.getWip_id(), client.getClient_id(), new Date(new java.util.Date().getTime()), quantity, "可用", 0.0);//默认数据
                int flag1 = qr.update(conn, "INSERT INTO finance.buy_wip(wip_id,client_id,buy_wip_time,buy_wip_quantity,buy_wip_assetstatus,buy_wip_earnings) VALUES (?,?,?,?,?,?)", buyWip.getWip_id(), buyWip.getClient_id(), buyWip.getBuy_wip_time(), buyWip.getBuy_wip_quantity(), buyWip.getBuy_wip_assetstatus(), buyWip.getBuy_wip_earnings());
                int flag2 = qr.update(conn, "UPDATE client SET client_balance=? where client_id=?", client.getClient_balance(), client.getClient_id());
                if (flag1 > 0 && flag2 > 0) {
                    //两个操作都成功
                    DbUtils.commitAndCloseQuietly(conn);//提交并关闭连接
                    return buyWip;
                } else {
                    //有一个操作不成功
                    DbUtils.rollbackAndCloseQuietly(conn);//回滚并关闭连接
                    return null;
                }
            } catch (SQLException e) {
                DbUtils.rollbackAndCloseQuietly(conn);
                throw new RuntimeException(e);
            }
        }
        //（4.2）执行以下事务：
        //        更新buy_wip对象中的quantity字段
        //        修改客户账户内余额
        //        结束事务，返回修改好的Buy_Wip类
        if (!buy_wips.isEmpty()) {
            //客户购买过该产品
            try {
                buyWip = buy_wips.get(0);//取出第一项购买理财产品记录，也只可能有一项记录
                conn = DBUtils.getConnection();
                //开始事务
                conn.setAutoCommit(false);
                quantity = buyWip.getBuy_wip_quantity() + quantity;//更新后的购买数量
                buyWip.setBuy_wip_quantity(quantity);
                int flag1 = qr.update(conn, "UPDATE buy_wip SET buy_wip_quantity=?", quantity);
                int flag2 = qr.update(conn, "UPDATE SET client_balance=? where client_id=?", client.getClient_balance(), client.getClient_id());
                if (flag1 > 0 && flag2 > 0) {
                    //两个操作都成功
                    DbUtils.commitAndCloseQuietly(conn);//提交并关闭连接
                    return buyWip;
                } else {
                    //有一个操作不成功
                    DbUtils.rollbackAndCloseQuietly(conn);//回滚并关闭连接
                    return null;
                }
            } catch (SQLException e) {
                DbUtils.rollbackAndCloseQuietly(conn);
                throw new RuntimeException(e);
            }
        }
        return null;//操作不成功
    }
}
